#include "Gwen/Controls/Button.h"
#include "Gwen/Controls/Property/NumericUpDown.h"
#include "Gwen/Controls/PropertyTree.h"
#include "PatchStomper/StomperModel.h"
#include "PatchStomper/ToolElements/GridSplitter.h"
#include "StompedReality/Math/Rectangle.h"
#include "StomperLib/RenderHelper.h"
namespace PatchStomper
{
GridSplitter::GridSplitter( StomperLib::BaseLayout* layout, StompedReality::IGame* game,
                            StomperLib::EditorCamera* camera ) : StomperLib::ToolElement( layout, game, camera )
{
  m_BaseSize = StompedReality::Math::Vector2( 0, 0 );
  m_SplitX = 5;
  m_SplitY = 5;
  m_OffsetX = 0;
  m_OffsetY = 0;

  this->CreateGui( layout );
}

GridSplitter::~GridSplitter( )
{
}

void GridSplitter::CalculateRects( )
{
  this->m_PositionList.clear( );

  float gridWidth = ((StomperModel*)Model)->TextureSize.GetX( ) / m_SplitX;
  float gridHeight = ((StomperModel*)Model)->TextureSize.GetY( ) / m_SplitY;

  int numSplitsX = ((StomperModel*)Model)->TextureSize.GetX( ) / gridWidth;
  int numSplitsY = ((StomperModel*)Model)->TextureSize.GetY( ) / gridHeight;

  m_BaseSize.SetX( gridWidth - m_OffsetX * 2 );
  m_BaseSize.SetY( gridHeight - m_OffsetY * 2 );

  for (int x = 0; x < m_SplitX; ++x)
  {
    for (int y = 0; y < m_SplitY; ++y)
    {
      this->m_PositionList.push_back( StompedReality::Math::Vector2( x * gridWidth + m_OffsetX, y * gridHeight +
                                                                     m_OffsetY ));
    }
  }
}

bool GridSplitter::IsPointInsideRect( const StompedReality::Math::Vector2 point )
{
  for (auto pos = this->m_PositionList.begin( ); pos != this->m_PositionList.end( ); ++pos)
  {
    if (StompedReality::Math::Rectangle::Contains( *pos, this->m_BaseSize, point ))
      return true;
  }

  return false;
}

StompedReality::Math::Vector2 GridSplitter::GetRectPos( const StompedReality::Math::Vector2 point )
{
  for (auto pos = this->m_PositionList.begin( ); pos != this->m_PositionList.end( ); ++pos)
  {
    if (StompedReality::Math::Rectangle::Contains( *pos, this->m_BaseSize, point ))
      return *pos;
  }

  return StompedReality::Math::Vector2( 0, 0 );
}

StompedReality::Math::Vector2 GridSplitter::BaseSize( )
{
  return this->m_BaseSize;
}

void GridSplitter::Draw( )
{
  if (!((StomperModel*)Model)->GridActive || ((StomperModel*)Model)->TextureSize.Length( ) < 1)
    return;

  for (auto pos = this->m_PositionList.begin( ); pos != this->m_PositionList.end( ); ++pos)
  {
    StomperLib::RenderHelper::DrawRect( *pos, *pos + this->m_BaseSize );
  }
}

bool GridSplitter::Update( )
{
  auto model = ((StomperModel*)Model);
  if (!model->GridActive || model->TextureSize.Length( ) < 1)
    return false;
  if (Model->Mode == GridClickAddPatchMode && this->GetInputSystem( )->IsLeftButtonPressed( ))
  {
    if (this->IsPointInsideRect( this->GetMousePos( )))
    {
      return model->Add( this->GetRectPos( this->GetMousePos( )), this->BaseSize( ));
    }
  }
  return false;
}

void GridSplitter::OnTextureChange( )
{
  this->CalculateRects( );
}

void GridSplitter::OnXChange( Gwen::Event::Info info )
{
  if (info.String.length( ) < 1 || this->Model == NULL)
    return;

  this->m_SplitX = atoi( info.String.c_str( ));
  this->CalculateRects( );
}

void GridSplitter::OnYChange( Gwen::Event::Info info )
{
  if (info.String.length( ) < 1 || this->Model == NULL)
    return;

  this->m_SplitY = atoi( info.String.c_str( ));
  this->CalculateRects( );
}

void GridSplitter::OnOffSetXChange( Gwen::Event::Info info )
{
  if (info.String.length( ) < 1 || this->Model == NULL)
    return;

  this->m_OffsetX = atoi( info.String.c_str( ));
  this->CalculateRects( );
}

void GridSplitter::OnOffSetYChange( Gwen::Event::Info info )
{
  if (info.String.length( ) < 1 || this->Model == NULL)
    return;

  this->m_OffsetY = atoi( info.String.c_str( ));
  this->CalculateRects( );
}

void GridSplitter::OnActivateChange( Gwen::Event::Info info )
{
  if (info.String.Get( ).compare( "1" ) == 0)
    ((StomperModel*)Model)->GridActive = true;
  else
    ((StomperModel*)Model)->GridActive = false;
}

void GridSplitter::CreateGui( StomperLib::BaseLayout* layout )
{
  auto window = layout->CreateSubWindow( "Grid Splitter", "Ctrl + Shift + s", false );
  Gwen::Controls::PropertyTree* ptree = new Gwen::Controls::PropertyTree( (Gwen::Controls::WindowControl*) window );
  ptree->Dock( Gwen::Pos::Fill );

  Gwen::Controls::Properties* splitProps = ptree->Add( L"Split" );

  auto xProp = new Gwen::Controls::Property::NumericUpDown( splitProps );
  xProp->GetNumericUpDown( )->AddDownAccelerator( "Left" );
  xProp->GetNumericUpDown( )->AddUpAccelerator( "Right" );
  splitProps->Add( L"X", xProp, L"5" )->onChange.Add( this, &GridSplitter::OnXChange );

  auto yProp = new Gwen::Controls::Property::NumericUpDown( splitProps );
  yProp->GetNumericUpDown( )->AddDownAccelerator( "Down" );
  yProp->GetNumericUpDown( )->AddUpAccelerator( "Up" );
  splitProps->Add( L"Y", yProp, L"5" )->onChange.Add( this, &GridSplitter::OnYChange );;

  splitProps->Add( L"OffSet X", new Gwen::Controls::Property::NumericUpDown( splitProps ), "0" )->onChange.Add(
    this, &GridSplitter::OnOffSetXChange );

  splitProps->Add( L"OffSet Y", new Gwen::Controls::Property::NumericUpDown( splitProps ), "0" )->onChange.Add(
    this, &GridSplitter::OnOffSetYChange );
  ptree->ExpandAll( );
}

}